package com.vietnam.power.dao.impl;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.vietnam.power.dao.TransactionDao;
import com.vietnam.power.domain.TransactionSearchCriteria;
import com.vietnam.power.persitence.PatronInfo;
import com.vietnam.power.persitence.Transaction;

@Repository
@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
public class TransactionDaoImpl extends GenericDaoImpl implements TransactionDao {

	@Transactional(readOnly = true)
	public Transaction getTransactionById(int id) {
		return findById(Transaction.class, id);
	}

	public void createTransaction(Transaction txn) {
		PatronInfo pi = txn.getPatronInfo();
		save(pi);
		save(txn);
	}

	@SuppressWarnings("unchecked")
	public List<Transaction> searchTransaction(TransactionSearchCriteria tsc) {
		Criteria crt = getSessionFactory().getCurrentSession().createCriteria(Transaction.class);
		if (StringUtils.isNotBlank(tsc.getTxnRefNo())) {
			crt.add(Restrictions.eq("transactionRefNumber", tsc.getTxnRefNo()));
		}

		if (StringUtils.isNotBlank(tsc.getPatronName()) || StringUtils.isNotBlank(tsc.getEmail()) || StringUtils.isNotBlank(tsc.getPhone())) {
			crt.createAlias("patronInfo", "patronInfo");
			if (StringUtils.isNotBlank(tsc.getPatronName())) {
				crt.add(Restrictions.ilike("patronInfo.fullName", tsc.getPatronName()));
			}
			if (StringUtils.isNotBlank(tsc.getEmail())) {
				crt.add(Restrictions.ilike("patronInfo.email", tsc.getEmail()));
			}
			if (StringUtils.isNotBlank(tsc.getPhone())) {
				crt.add(Restrictions.ilike("patronInfo.phone", tsc.getPhone()));
			}
			if (tsc.getPatronInfoId() != null) {
				crt.add(Restrictions.eq("patronInfo.id", tsc.getPatronInfoId()));
			}
		}

		if (tsc.getOrderStatus() != null) {
			crt.add(Restrictions.eq("orderStatus", tsc.getOrderStatus()));
		}

		if (tsc.getCreatedDate() != null) {
			Date maxDate = new Date(tsc.getCreatedDate().getTime() + TimeUnit.DAYS.toMillis(1));

			Conjunction and = Restrictions.conjunction();
			and.add(Restrictions.ge("createdDate", tsc.getCreatedDate()));
			and.add(Restrictions.lt("createdDate", maxDate));
			crt.add(and);
		}

		if (tsc.getPaymentId() != null) {
			crt.createAlias("paymentMethod", "paymentMethod");
			crt.add(Restrictions.eq("paymentMethod.id", tsc.getPaymentId()));
		}

		if (StringUtils.isNotBlank(tsc.getProductName())) {
			crt.createAlias("txnProducts", "txnProducts");
			crt.createAlias("txnProducts.product", "product");
			crt.add(Restrictions.ilike("product.name", tsc.getProductName()));
		}
		
		crt.addOrder(Order.desc("createdDate"));

		return crt.list();
	}

	public void updatePatron(PatronInfo pi) {
		merge(pi);
	}

	public PatronInfo getPatronInfoById(int id) {
		return findById(PatronInfo.class, id);
	}

	public void updateTransaction(Transaction txn) {
		merge(txn);
	}
}
